package com.ruben.simplescaffold.plugin;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.ruben.simplescaffold.entity.UserDetail;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;


/**
 * @author <achao1441470436@gmail.com>
 * @since 2022/4/10 13:54
 */
@Component
@Intercepts(
		{
				@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
				@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
		}
)
public class MybatisExecutorQueryPlugin implements Interceptor {

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		Executor executor = (Executor) invocation.getTarget();
		Object[] args = invocation.getArgs();
		Method method = invocation.getMethod();

		MappedStatement ms = (MappedStatement) args[0];
		Object parameter = args[1];
		BoundSql boundSql;
		if (args.length == 4) {
			boundSql = ms.getBoundSql(parameter);
		} else {
			boundSql = (BoundSql) args[5];
		}
		// 反射工具类，可以修改sql语句等
		MetaObject metaObject = SystemMetaObject.forObject(boundSql);
		String sql = (String) metaObject.getValue("sql");
		if (!StrUtil.containsIgnoreCase(sql, SqlKeyword.ORDER_BY.getSqlSegment())) {
			// 更改sql
			metaObject.setValue("sql", sql + " order by id asc");
		}
		return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}
}
